%     FASTENER DOCTOR - программа для лечения и конвертации крепежа
%     Copyright (C) 2018  Михаил Козлов
%     Сайт проекта: <http://www.fastenerdoctor.ru/>
%     Адрес электронной почты для связи с разработчиком:
%     <doctor.fastener@gmail.com>
% 
%     Эта программа является свободным программным обеспечением: Вы можете
%     распространять ее и/или изменять, соблюдая условия Универсальной общественной
%     лицензии GNU, опубликованной Фондом свободного программного обеспечения,
%     либо редакции 3, либо (на Ваше усмотрение) любой редакции, выпущенной позже.
% 
%     Эта программа распространяется в надежде на то, что она окажется полезной,
%     но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, включая даже подразумеваемую гарантию ТОВАРНОЙ ПРИГОДНОСТИ,
%     либо ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Ознакомьтесь с Универсальной общественной
%     лицензией GNU для получения более подробной информации.
% 
%     Вы должны были получить копию Универсальной общественной лицензии GNU
%     вместе с этой программой. Если Вы ее не получили, то перейдите по адресу:
%     <http://www.gnu.org/licenses/>.
% 
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
% 
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%     GNU General Public License for more details.
% 
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <https://www.gnu.org/licenses/>.

function DB_PSet_Delete(PSet_ID)

global ErrCode;

global DB_PSETS;
global DB_FIELDS;

global AST_PSETS;
global AST_COORD;
global AST_MATERIALS;

global AT_PSETS;
global AT_FIELDS;
global AT_COORD;
global AT_MATERIALS;

Pset_delete_protection_policy = 1; % ( 0 | 1 ) Политика защиты от удаления property set: 0 - удаление разрешено; ассоциированные элементы отвязываются от property set (установка по умолчанию в Patran);
                                   %                                                     1 - удаление запрещено, если с property set ассоциированы элементы.

% Проверка существования в базе property set
if (~DB_PSet_Exist(PSet_ID))
    fprintf (1, '\nОшибка функции DB_PSet_Delete: property set с номером %i отсутствует в базе !\n', PSet_ID);
    ErrCode = -1;
    return;
end

% Список ассоциированных элементов
Elm_list = AST_PSETS{AT_PSETS(PSet_ID)}.Elm_list;

if (~isempty(Elm_list))

    % Защита от удаления property set
    if (Pset_delete_protection_policy == 1)
        if (size(Elm_list,1) == 1)
            elm_word = 'со следующим элементом';
        else
            elm_word = 'со следующими элементами';
        end
        fprintf (1, '\nОшибка функции DB_PSet_Delete: property set с номером %i [%s] не может быть удален, так как ассоциирован %s:\n', PSet_ID, DB_PSETS{AT_PSETS(PSet_ID)}.Patran_name, elm_word);
        column_print_counter = 0;
        row_print_counter = 0;
        for j=1:size(Elm_list,1)
            fprintf (1, ' %i', Elm_list(j));
            column_print_counter = column_print_counter + 1;
            if (column_print_counter == 10)
                column_print_counter = 0;
                row_print_counter = row_print_counter + 1;
                fprintf (1, '\n');
            end
            if (row_print_counter == 10)
                break;
            end
        end
        if (j < size(Elm_list,1))
            fprintf (1, '(показано %i элементов из %i)\n', j, size(Elm_list,1));
        else
            fprintf (1, '\n');
        end
        ErrCode = -1;
        return;
    end

    % Отвязывание элементов от property set
    DB_Elm_Modify_Pset(Elm_list, []);
    
end

% Внесение изменений в таблицу ассоциативности систем координат
switch DB_PSETS{AT_PSETS(PSet_ID)}.type
    case 'PSOLID'
        if (DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID > 0)
            AST_COORD{AT_COORD(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID)}.PSet_list = setdiff(AST_COORD{AT_COORD(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID)}.PSet_list, PSet_ID);
            if (isempty(AST_COORD{AT_COORD(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID)}.PSet_list))
                AST_COORD{AT_COORD(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID)}.PSet_list = [];
            end
        end
    case {'PCOMP', 'PCOMPG', 'PSHELL'}
        if (~DB_Field_Isempty(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID))
            SHELL_CID_counter = 0;
            if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Default(1) == 0)
                if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Default(2) > 0)
                    SHELL_CID_counter = SHELL_CID_counter + 1;
                end
            end
            for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.ID_data, 1)
                if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.ID_data{j} ~= -1)
                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Value_data{j}(1) == 0)
                        if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Value_data{j}(2) > 0)
                            SHELL_CID_counter = SHELL_CID_counter + 1;
                        end
                    end
                end
            end
            if (SHELL_CID_counter > 0)
                SHELL_CID_Array = zeros(SHELL_CID_counter,1);
                SHELL_CID_counter = 0;
                if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Default(1) == 0)
                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Default(2) > 0)
                        SHELL_CID_counter = SHELL_CID_counter + 1;
                        SHELL_CID_Array(SHELL_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Default(2);
                    end
                end
                for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.ID_data, 1)
                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.ID_data{j} ~= -1)
                        if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Value_data{j}(1) == 0)
                            if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Value_data{j}(2) > 0)
                                SHELL_CID_counter = SHELL_CID_counter + 1;
                                SHELL_CID_Array(SHELL_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID)}.Value_data{j}(2);
                            end
                        end
                    end
                end
                SHELL_CID_Array = unique(SHELL_CID_Array);
                for j=1:size(SHELL_CID_Array,1)
                    AST_COORD{AT_COORD(SHELL_CID_Array(j))}.PSet_list = setdiff(AST_COORD{AT_COORD(SHELL_CID_Array(j))}.PSet_list, PSet_ID);
                    if (isempty(AST_COORD{AT_COORD(SHELL_CID_Array(j))}.PSet_list))
                        AST_COORD{AT_COORD(SHELL_CID_Array(j))}.PSet_list = [];
                    end
                end
            end
        end
    case 'PBUSH'
        if (~DB_Field_Isempty(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID))
            PBUSH_CID_counter = 0;
            if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.Default > 0)
                PBUSH_CID_counter = PBUSH_CID_counter + 1;
            end
            for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.ID_data, 1)
                if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.ID_data{j} ~= -1)
                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.Value_data{j} > 0)
                        PBUSH_CID_counter = PBUSH_CID_counter + 1;
                    end
                end
            end
            if (PBUSH_CID_counter > 0)
                PBUSH_CID_Array = zeros(PBUSH_CID_counter,1);
                PBUSH_CID_counter = 0;
                if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.Default > 0)
                    PBUSH_CID_counter = PBUSH_CID_counter + 1;
                    PBUSH_CID_Array(PBUSH_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.Default;
                end
                for j=1:size(DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.ID_data, 1)
                    if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.ID_data{j} ~= -1)
                        if (DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.Value_data{j} > 0)
                            PBUSH_CID_counter = PBUSH_CID_counter + 1;
                            PBUSH_CID_Array(PBUSH_CID_counter) = DB_FIELDS{AT_FIELDS(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID)}.Value_data{j};
                        end
                    end
                end
                PBUSH_CID_Array = unique(PBUSH_CID_Array);
                for j=1:size(PBUSH_CID_Array,1)
                    AST_COORD{AT_COORD(PBUSH_CID_Array(j))}.PSet_list = setdiff(AST_COORD{AT_COORD(PBUSH_CID_Array(j))}.PSet_list, PSet_ID);
                    if (isempty(AST_COORD{AT_COORD(PBUSH_CID_Array(j))}.PSet_list))
                        AST_COORD{AT_COORD(PBUSH_CID_Array(j))}.PSet_list = [];
                    end
                end
            end
        end
    case {'PROD', 'PBMSECT', 'PBRSECT', 'PBAR', 'PBARL', 'PBEAM', 'PBEAML', 'PBCOMP'}
        % Ничего не делаем
    otherwise
        fprintf (1, '\nОшибка функции DB_PSet_Delete: обнаружен неизвестный тип property set с номером %i [%s] !\n', PSet_ID, DB_PSETS{AT_PSETS(PSet_ID)}.type);
        fprintf (1, 'Обратитесь к разработчику для решения этого вопроса.\n');
        ErrCode = -1;
        return;
end

% Внесение изменений в таблицу ассоциативности материалов
switch DB_PSETS{AT_PSETS(PSet_ID)}.type
    case {'PCOMP', 'PCOMPG'}
        Mat_array = unique(DB_PSETS{AT_PSETS(PSet_ID)}.Laminate(:,1));
        for j=1:size(Mat_array,1)
            AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list = setdiff(AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list, PSet_ID);
            if (isempty(AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list))
                AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list = [];
            end
        end
    case 'PSHELL'
        Mat_array = zeros(3,1);
        Mat_array(1) = DB_PSETS{AT_PSETS(PSet_ID)}.Mat_ID_membrane;
        Mat_array(2) = DB_PSETS{AT_PSETS(PSet_ID)}.Mat_ID_bending;
        Mat_array(3) = DB_PSETS{AT_PSETS(PSet_ID)}.Mat_ID_transverse_shear;
        Mat_array = unique(Mat_array);
        for j=1:size(Mat_array,1)
            AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list = setdiff(AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list, PSet_ID);
            if (isempty(AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list))
                AST_MATERIALS{AT_MATERIALS(Mat_array(j))}.PSet_list = [];
            end
        end
    case 'PBUSH'
        % Ничего не делаем
    case {'PSOLID', 'PROD', 'PBMSECT', 'PBRSECT', 'PBAR', 'PBARL', 'PBEAM', 'PBEAML', 'PBCOMP'}
        AST_MATERIALS{AT_MATERIALS(DB_PSETS{AT_PSETS(PSet_ID)}.Mat_ID)}.PSet_list = setdiff(AST_MATERIALS{AT_MATERIALS(DB_PSETS{AT_PSETS(PSet_ID)}.Mat_ID)}.PSet_list, PSet_ID);
        if (isempty(AST_MATERIALS{AT_MATERIALS(DB_PSETS{AT_PSETS(PSet_ID)}.Mat_ID)}.PSet_list))
            AST_MATERIALS{AT_MATERIALS(DB_PSETS{AT_PSETS(PSet_ID)}.Mat_ID)}.PSet_list = [];
        end
    otherwise
        fprintf (1, '\nОшибка функции DB_PSet_Delete: обнаружен неизвестный тип property set с номером %i [%s] !\n', PSet_ID, DB_PSETS{AT_PSETS(PSet_ID)}.type);
        fprintf (1, 'Обратитесь к разработчику для решения этого вопроса.\n');
        ErrCode = -1;
        return;
end

% Удаление полей
switch DB_PSETS{AT_PSETS(PSet_ID)}.type
    case {'PCOMP', 'PCOMPG', 'PSHELL'}
        Field_list = zeros(2,1);
        Field_list(1) = DB_PSETS{AT_PSETS(PSet_ID)}.Ori_Field_ID;
        Field_list(2) = DB_PSETS{AT_PSETS(PSet_ID)}.Offset_Field_ID;
        DB_Field_Delete(Field_list);
		if (ErrCode < 0)
			return;
		end
    case 'PBUSH'
        DB_Field_Delete(DB_PSETS{AT_PSETS(PSet_ID)}.Ori_CID_Field_ID);
		if (ErrCode < 0)
			return;
		end
    case {'PBMSECT', 'PBRSECT', 'PBAR', 'PBARL', 'PBEAM', 'PBEAML', 'PBCOMP'}
        Field_list = zeros(5,1);
        Field_list(1) = DB_PSETS{AT_PSETS(PSet_ID)}.Ori_vector_Field_ID;
        Field_list(2) = DB_PSETS{AT_PSETS(PSet_ID)}.Offset_vector_A_Field_ID;
        Field_list(3) = DB_PSETS{AT_PSETS(PSet_ID)}.Offset_vector_B_Field_ID;
        Field_list(4) = DB_PSETS{AT_PSETS(PSet_ID)}.Pinned_DOFs_A_Field_ID;
        Field_list(5) = DB_PSETS{AT_PSETS(PSet_ID)}.Pinned_DOFs_B_Field_ID;
        DB_Field_Delete(Field_list);
		if (ErrCode < 0)
			return;
		end
    case {'PSOLID', 'PROD'}
        % Ничего не делаем
    otherwise
        fprintf (1, '\nОшибка функции DB_PSet_Delete: обнаружен неизвестный тип property set с номером %i [%s] !\n', PSet_ID, DB_PSETS{AT_PSETS(PSet_ID)}.type);
        fprintf (1, 'Обратитесь к разработчику для решения этого вопроса.\n');
        ErrCode = -1;
        return;
end

% Удаление property set из базы данных и адресной таблицы
DB_PSETS{AT_PSETS(PSet_ID)}.ID = -1;
AT_PSETS(PSet_ID) = 0;
